#ifndef _IPL_WRAPPING_FNCS_H_
#define _IPL_WRAPPING_FNCS_H_

#include "../PreHeader.h"
#include "../PreDefine.h"
#include "Box2D.h"
// C Headers
#include <math.h>
#include <time.h>


//#define ENABLE_QUADS
//#define IPL_HAVE_MESSED_UP_QUADS

#ifdef WIN32
#else
#define glOrtho glOrthof
#endif


//#endif //defined GL_FIXED

#ifdef WIN32
#else
//!AC_ Temp
#define GL_QUADS GL_LINE_STRIP
#endif

#define IPL_MSE_MODELVIEW			GL_MODELVIEW
#define IPL_MSE_PROJECTION			GL_PROJECTION
#define IPL_MSE_MATRIX_MODE			GL_MATRIX_MODE

#define IPL_FLOAT_PI				3.14159f

#ifdef WIN32
// RUIZD: Created for the iPhone port (arbitrary values just for test!)
#define GL_PALETTE8_RGBA8_OES				9999
#define GL_UNSIGNED_SHORT_4_4_4_4			GL_UNSIGNED_SHORT
#define GL_UNSIGNED_SHORT_5_6_5				GL_UNSIGNED_SHORT
#define GL_UNSIGNED_SHORT_5_5_5_1			GL_UNSIGNED_SHORT
#define GL_TEXTURE_RECTANGLE_ARB			GL_TEXTURE_2D
#define GL_TEXTURE_CROP_RECT_OES			0
#else // iPhone
// The constants are already defined in iPhone
#endif


enum tIPLBuiltinStateVector
{
	IPL_BSV_UNIFORMBLENDING,
	IPL_BSV_A8NEARESTMODWITHUNIFORMBLENDING,
	IPL_BSV_A8LINEARMODWITHUNIFORMBLENDING,
	IPL_BSV_P8_8888NEARESTBLENDING,
	IPL_BSV_P8_8888LINEARBLENDING,
	IPL_BSV_4444NEARESTBLENDING,
	IPL_BSV_4444LINEARBLENDING,
	IPL_BSV_4444LINEARMODWITHUNIFORMBLENDING,
	IPL_BSV_565NEAREST,
	IPL_BSV_565LINEAR,
	IPL_BSV_565LINEARMODWITHUNIFORM,
	IPL_BSV_5551NEARESTBLENDING,
	IPL_BSV_5551LINEARBLENDING,
	IPL_BSV_8888NEARESTBLENDING,
	IPL_BSV_8888LINEARBLENDING,
	IPL_BSV_P8_565NEAREST
};

#define ORTHO_LEFT		(0.0f)
#define ORTHO_RIGHT		(SCREEN_WIDTH)
#define ORTHO_TOP		(0.0f)
#define ORTHO_BOTTOM	(SCREEN_HEIGHT)
#define ORTHO_NEAR		(-1.0f)
#define ORTHO_FAR		(1.0f)

extern GLfloat IPL_STANDARD_ORTHO_MATRIX[16];


// ---------------------------------------------------------------------------------
// IPLGLMatrixStack wrapping functions
// ---------------------------------------------------------------------------------

inline void IPLGLMatrixStack_LoadIdentity(void)
{
	glLoadIdentity();
};

// RUIZD: Chequear los valores entrantes de mode
inline void IPLGLMatrixStack_MatrixMode(GLenum mode)
{
	glMatrixMode(mode);
}

#ifdef WIN32
extern float tmpmat[16];
#endif
inline void IPLGLMatrixStack_LoadMatrixx(const GLfloat *m)
{
#ifdef WIN32
	for(int i=0; i<16; i++)
	{
		tmpmat[i] = (m[i]);
	}
	glLoadMatrixf(tmpmat);
#else
	glLoadMatrixf(m);
#endif
}



inline void IPLGLMatrixStack_Orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearz, GLfloat farz)
{
	/*GLfloat width = right-left;
	GLfloat height = top-bottom;


	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	float32 ratio = float32(width) / float32(height);

	b2Vec2 extents(ratio * 25.0f, 25.0f);
	extents *= viewZoom;

	b2Vec2 lower = viewCenter - extents;
	b2Vec2 upper = viewCenter + extents;*/

	//// L/R/B/T
	//gluOrtho2D(lower.x, upper.x, lower.y, upper.y);
#ifdef WIN32	
	glOrtho(left, right, bottom, top, nearz, farz);
#else // iPhone
	glOrthof(left, right, bottom, top, nearz, farz);
#endif
}

inline void IPLGLMatrixStack_PopMatrix(void)
{
	glPopMatrix();
}

inline void IPLGLMatrixStack_PushMatrix()
{ 
	glPushMatrix();
}

inline void IPLGLMatrixStack_Rotatex(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
#ifdef WIN32
	glRotatef((angle), (x), (y), (z));
#else
	glRotatef(angle, x, y, z);
#endif
}

inline void IPLGLMatrixStack_Scalex(GLfloat x, GLfloat y, GLfloat z)
{
#ifdef WIN32
	glScalef((x), (y), (z));
#else
	glScalef(x, y, z);
#endif
}

inline void IPLGLMatrixStack_Translatex(GLfloat x, GLfloat y, GLfloat z)
{
#ifdef WIN32
	glTranslatef((x), (y), (z));
#else
	glTranslatef(x, y, z);
#endif
}

inline void IPLGLMatrixStack_GetIntegerv(GLenum pname, GLint *params)
{
	glGetIntegerv(pname, params);
}

inline void IPLGLMatrixStack_Perspectivex(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
{
// RUIZD: Implementar esto
#ifdef WIN32
#else
#endif
}

// ---------------------------------------------------------------------------------
// IPLGLStateVector wrapping functions
// ---------------------------------------------------------------------------------
inline GLfloat IPLMath_IntToFixed(int n) { return (GLfloat)(n); }
inline GLfloat IPLMath_FloatToFixed(float n) { return (GLfloat) (n); }
inline GLfloat IPLMath_FixedDiv(int a, int b)
{
	return ((float)a / (float)b);
}

inline GLint IPLMath_FixedToInt(GLfloat n)
{
	return (GLint)(n);
}

inline GLfloat IPLMath_FixedMul(GLfloat a, GLfloat b)
{
	// RUIZD: We need to convert to INT in order to obtain a correct result in FX32
	// Because if a is FX32 and b is FX32 too, we cannot multiply to obtain another FX32. So:
	// a * P * b * P  / P = a * b * P^2 / P = a * b * P
	return (a * b);
}

inline GLfloat IPLMath_FixedTruncate(GLfloat a)
{
	return (float)(int)(a);
}

inline GLfloat IPLMath_FixedSin(GLfloat rad)
{
	// RUIZD: Warning: We are losing precision here
	return (sin((rad)));
}

inline GLfloat IPLMath_FixedCos(GLfloat rad)
{
	// RUIZD: Warning: We are losing precision here
	return (cos((rad)));
}

inline GLfloat IPLMath_FixedAtan2(GLfloat y, GLfloat x)
{
	// RUIZD: Warning: We are losing precision here
	return (atan2((y), (x)));
}

inline GLfloat IPLMath_FixedSqrt(GLfloat x)
{
	// RUIZD: Warning: We are losing precision here
	return (sqrt((x)));
}



// ---------------------------------------------------------------------------------
// IPLGLStateVector wrapping functions
// ---------------------------------------------------------------------------------
#define IPL_BSV_CUSTOM_1			0
inline void IPLGLStateVector_SetCurrentToBuiltin(GLenum state)
{
}

// ---------------------------------------------------------------------------------
// tIPLRect structure
// ---------------------------------------------------------------------------------
struct tIPLRect
{
	GLfloat mX;
	GLfloat mY;
	GLfloat mW;
	GLfloat mH;
};

// ---------------------------------------------------------------------------------
// tIPLTime wrapping functions
// ---------------------------------------------------------------------------------
typedef struct 
{ 
    unsigned int mSecond; 
    unsigned int mMinute; 
    unsigned int mHour; 
    unsigned int mDay; 
    unsigned int mMonth; 
    unsigned int mYear; 
}tIPLTime;

void IPLHWUtil_GetTime(tIPLTime* poutTime);

inline void IPLGLUtil_ResetGL()
{
	// RUIZD: Code it
}

// ---------------------------------------------------------------------------------
// IPLFile wrapping functions
// ---------------------------------------------------------------------------------
// ...

// ---------------------------------------------------------------------------------
// IPLUpdate enums
// ---------------------------------------------------------------------------------
enum eIPLUpdateStatus 
{ 
  IPL_US_APP_REQUESTS_EXIT 
 ,IPL_US_APP_IDLE 
 ,IPL_US_APP_ACTIVE 
}; 

// ---------------------------------------------------------------------------------
// IPLInput enums
// ---------------------------------------------------------------------------------
enum eIPLInputCode 
{ 
  IPL_IC_NOKEY 
 ,IPL_IC_MENU 
 ,IPL_IC_SELECT 
 ,IPL_IC_NEXT 
 ,IPL_IC_PREV 
 ,IPL_IC_PLAYPAUSE 
 ,IPL_IC_WHEEL 
};

enum eIPLInputType 
{ 
  IPL_IT_NOTYPE 
 ,IPL_IT_UP 
 ,IPL_IT_DOWN 
};

// ---------------------------------------------------------------------------------
// Sound stuff
// Note that not all the related sound stuff is wrapped, the problem is that the way
// that the sound is managed in iPod is very different to iPhone/Touch so is a better
// choice to reimplement the body of the cSound class, keep most of the interface and
// remove the IPL method calls. We only keep one enum.
// ---------------------------------------------------------------------------------
typedef enum 
{ 
  IPL_PS_PLAYBACK_STOPPED = 0, 
  IPL_PS_PLAYBACK_PLAYING, 
  IPL_PS_PLAYBACK_PAUSED 
} eIPLPlaybackState;

inline void IPLHWUtil_SetMasterVolume(int n)
{
}

inline int IPLHWUtil_GetMasterVolume()
{
	return 10;
}

// ---------------------------------------------------------------------------------
// IPLExit enum
// ---------------------------------------------------------------------------------
enum eIPLExitStatus 
{ 
  IPL_ES_EXITING 
 ,IPL_ES_EXITED 
};


#define IPL_CVS_1									0
#define gVector_565LinearModWithColorDepth			0
#define gVectorLen_565LinearModWithColorDepth		0
#define gVectorAttribs_565LinearModWithColorDepth	0
inline void IPLGLStateVector_LoadCustom(int a, int b, int c, int d)
{
	// RUIZD: Implement this
}


// ---------------------------------------------------------------------------------
// IPLGeometry wrapping functions
// ---------------------------------------------------------------------------------
typedef struct 
{ 
    GLenum  mGeometryMode; 
    GLsizei mCount; 
    GLfloat* mpVertexPositions; 
    GLfloat* mpVertexColors; 
    GLfloat* mpTextureCoords; 
    GLfloat* mpVertexNormals; 
} tIPLGeometry;

void IPLGeometry_DrawDirect(tIPLGeometry * geom);
void IPLGeometry_DrawDirectLinearAdd(tIPLGeometry * geom);
// ---------------------------------------------------------------------------------
// Util wrapping functions
// ---------------------------------------------------------------------------------
inline void IPLHWUtil_SetBackLight(int n)
{
}

#endif // _IPL_WRAPPING_FNCS_H_